package com.chukun.rpc.registry;

import com.chukun.rpc.protocol.InvokerProtocol;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class RegistryHandler extends ChannelInboundHandlerAdapter {

    public static Map<String,Object> registryMap = new ConcurrentHashMap<>();

    private List<String> classNames = new ArrayList<>();

    public RegistryHandler() {
        // 完成服务扫描
        scannerClass("com.chukun.rpc.provider");
        // 注册
        doRegistry();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Object result = new Object();
        if (msg instanceof InvokerProtocol) {
            InvokerProtocol request = (InvokerProtocol) msg;
            if (registryMap.containsKey(request.getClassName())) {
                Object clazz = registryMap.get(request.getClassName());
                Method method = clazz.getClass().getDeclaredMethod(request.getMethodName(), request.getParamters());
                result = method.invoke(clazz,request.getParamterValues());
                ctx.writeAndFlush(result);
            }
        }
        ctx.close();
    }


    private void scannerClass(String packageName) {
        URL url = this.getClass().getClassLoader().getResource(packageName.replaceAll("\\.", "/"));
        File dir = new File(url.getFile());
        for (File file : dir.listFiles()) {
            if (file.isDirectory()) {
                scannerClass(packageName+"/" +file.getName());
            }else {
                classNames.add(packageName +"."+file.getName().replace(".class","").trim());
            }
        }
    }

    /**
     * 注册
     */
    private void doRegistry() {
        if (classNames.size() == 0) {
            return;
        }
        for (String className : classNames) {
            try {
                Class<?> clazz = Class.forName(className);
                Class<?> anInterface = clazz.getInterfaces()[0];
                registryMap.put(anInterface.getName(), clazz.newInstance());
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}
